﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using FEM.Basic;
using PGMHelper;
using PerformIndex;
using Login;
using Newtonsoft.Json;
using SectionAnalysis;
using FEM.Result;

namespace PBSD_Development
{
    public class WallSection : Section
    {
        /// <summary>
        /// 剪力墙截面
        /// </summary>
        private WALL_Section wallSection
        {
            get
            {
                return (WALL_Section)this.secion;
            }
        }

        /// <summary>
        /// I端边缘构件
        /// </summary>
        private WallBoundarySection boundaryI { set; get; }

        /// <summary>
        /// J端边缘构件
        /// </summary>
        private WallBoundarySection boundaryJ { set; get; }

        /// <summary>
        /// 竖向分布筋配筋率
        /// </summary>
        private double vRatio { set; get; }

        /// <summary>
        /// 边缘构件体积配箍率
        /// </summary>
        public double bStirrupVRatio { set; get; }

        /// <summary>
        /// 腹部剪力墙长度
        /// </summary>
        private double webWallLength
        {
            get
            {
                return this.wallSection.Length - this.boundaryI.bLength - this.boundaryJ.bLength;
            }
        }

        /// <summary>
        /// 获得等效高度
        /// </summary>
        /// <returns></returns>
        protected override double GetSectionHeight()
        {
            return this.wallSection.Length;
        }

        /// <summary>
        /// 是否型钢截面
        /// </summary>
        /// <returns></returns>
        private bool isSRCSection()
        {
            return this.Asteel != 0;
        }

        /// <summary>
        /// 截面信息是否完整
        /// </summary>
        /// <returns></returns>
        protected override bool isSectionCorrect()
        {
            //长度是否正确
            if(this.wallSection.Length <= 0) return MessageBoxExtern.Error("剪力墙长度错误！");
            if (this.wallSection.Thickness <= 0) return MessageBoxExtern.Error("剪力墙厚度错误！");
            if (this.webWallLength < 0)  return MessageBoxExtern.Error("剪力墙边缘构件溢出！");
            //边缘构件是否正确
            if (!this.boundaryI.isCorrect() || !this.boundaryJ.isCorrect())
                return false;
            //配筋
            if(this.vRatio <= 0 || this.wallSection.Stirrup_S_Ratio <= 0)
                return MessageBoxExtern.Error("剪力墙分布筋错误！");
            //剪跨长度
            if (this.shearSpan <= 0)
                return MessageBoxExtern.Error("未设定剪跨长度！");
            //材料强度
            if (this.wallSection.Concrete_Grade <= 0 || this.wallSection.Bar_Grade <= 0
               || this.wallSection.Stirrup_Grade <= 0)
                return MessageBoxExtern.Error("未设定材料强度！");
            //SRC截面
            if (this.isSRCSection())
            {
                return this.wallSection.Steel_Grade <= 0 ?
                      MessageBoxExtern.Error("未设定型钢材料强度！") : true;
            }
            return true;
        }

        #region 承载力

        /// <summary>
        /// 设定剪力墙子墙数据
        /// </summary>
        private bool SetWallSubSection()
        {
            //截面信息是否有误
            if (!this.isSectionCorrect()) return false;
            //初始化
            this.wallSection.Sub_Section_List = new List<Wall_Sub_Section>();
            //端部截面
            var bSectionI = this.boundaryI.GetWall_Sub_Section(this.wallSection);
            var bSectionJ = this.boundaryJ.GetWall_Sub_Section(this.wallSection);
            //中间段剪力墙
            var mideSection = new Wall_Sub_Section
            {
                is_Confined = false,
                Length = (float)this.webWallLength,
                As_Ratio = (float)(this.vRatio * 100),
                Fiber_Number = 5,
                Stirrup_V_Ratio = (float)this.bStirrupVRatio,
                Stirrup_Space = 100,
            };
            //i
            if (bSectionI.Length > 0) this.wallSection.Sub_Section_List.Add(bSectionI);
            if (this.webWallLength > 100) this.wallSection.Sub_Section_List.Add(mideSection);
            if (bSectionJ.Length > 0) this.wallSection.Sub_Section_List.Add(bSectionJ);
            //剖分截面
            this.wallSection.SetFiberInfo();
            return true;
        }

        /// <summary>
        /// 设定抗剪承载力
        /// </summary>
        private bool setShearCapacity()
        {
            //截面信息是否有误
            if (!this.isSectionCorrect()) return false;
            //计算剪跨比
            var lamda = (float)this.Lammda;
            //计算抗剪承载力
            var design = ShearCapacityHelper.GetCapacity(this.wallSection,
                        lamda, (float)this.axialLoad, ShearCapacityHelper.CapacityType.Design);
            var basic = ShearCapacityHelper.GetCapacity(this.wallSection,
                        lamda, (float)this.axialLoad, ShearCapacityHelper.CapacityType.Basic);
            var avg = ShearCapacityHelper.GetCapacity(this.wallSection,
                        lamda, (float)this.axialLoad, ShearCapacityHelper.CapacityType.Average);
            this.ShearCapacity = new CapacityObj(design, basic, avg);
            //完成承载力设定
            return true;
        }

        /// <summary>
        /// 设定抗弯承载力
        /// </summary>
        /// <returns></returns>
        private bool setMomentCapacity(int theta)
        {
            //截面信息是否有误
            if (!this.isSectionCorrect()) return false;
            //初始化截面分析结果
            SectionAnalysisResult saSection;
            //上传信息
            string zipJson = ZipHelper.CompressString(JsonConvert.SerializeObject(this.wallSection));
            //截面分析
            if (!this.setMomentCapacity(zipJson, theta, out saSection)) return false;
            //完成承载力设定
            return true;
        }

        /// <summary>
        /// 设定承载力
        /// </summary>
        /// <returns></returns>
        public bool SetCapacity(int theta)
        {
            //截面信息是否有误
            if (!this.isSectionCorrect()) return false;
            //设定剪力墙子截面
            if (!this.SetWallSubSection()) return false;
            //设定抗弯承载力
            if (!this.setMomentCapacity(theta)) return false;
            //设定抗剪承载力
            if (!this.setShearCapacity()) return false;
            //计算弯剪比
            var momentCaBasic = this.GetMomentCapacity(CapacityType.AverageValue);
            var shearCaBasic = this.GetShearCapacity(CapacityType.AverageValue);
            this.msr = Math.Abs(momentCaBasic / (shearCaBasic * this.shearSpan));
            return true;
        }

        /// <summary>
        /// 计算抗剪承载力
        /// </summary>
        /// <param name="capacity"> 抗剪承载力 </param>
        /// <returns> 成功 </returns>
        public override bool GetShearCapacityObj(out CapacityObj capacity)
        {
            capacity = this.ShearCapacity;
            if (!this.setShearCapacity()) return false;
            capacity = this.ShearCapacity;
            return true;
        }

        /// <summary>
        /// 轴压比
        /// </summary>
        public override double AxialLoadRatio
        {
            get
            {
                //截面信息是否有误
                if (!this.isSectionCorrect()) return 0;
                //混凝土面积
                var Ac = this.Ac;
                //型钢面积
                var As = this.Asteel;
                //获得强度平均值
                var fc = ShearCapacityHelper.GetConcreteStrength(this.wallSection.Concrete_Grade, 
                    false, ShearCapacityHelper.CapacityType.Basic);
                var fy = ShearCapacityHelper.GetSteelStrength(this.wallSection.Steel_Grade, ShearCapacityHelper.CapacityType.Basic);
                //确定分母
                var divide = fc * (Ac - As) + fy * As;
                //分母是否合法
                return divide == 0 ? 0 : -this.axialLoad / divide;
            }
        }

        /// <summary>
        /// 混凝土面积
        /// </summary>
        private double Ac
        {
            get
            {
                var thick = this.wallSection.Thickness;
                return this.boundaryI.GetConcreteArea(thick) +
                    this.boundaryJ.GetConcreteArea(thick) +
                    this.webWallLength * thick;
            }
        }

        /// <summary>
        /// 型钢面积
        /// </summary>
        private double Asteel
        {
            get
            {
                var thick = this.wallSection.Thickness;
                return this.wallSection.Steel_Thickness * this.wallSection.Length +
                    this.boundaryI.GetSteelArea(thick) +
                    this.boundaryJ.GetSteelArea(thick);
            }
        }

        /// <summary>
        /// 含钢率
        /// </summary>
        private double SteelRatio
        {
            get
            {
                return this.Asteel / this.Ac;
            }
        }

        /// <summary>
        /// 配箍特征值
        /// </summary>
        private double LamdaV
        {
            get
            {
                //混凝土强度
                var fc = ShearCapacityHelper.GetConcreteStrength(this.wallSection.Concrete_Grade,
                    false, ShearCapacityHelper.CapacityType.Basic);
                //箍筋强度
                var fyh = ShearCapacityHelper.GetSteelStrength(this.wallSection.Stirrup_Grade,
                    ShearCapacityHelper.CapacityType.Basic);
                //返回
                return this.bStirrupVRatio * fyh / fc;
            }
        }

        #endregion

        /// <summary>
        /// 设定变形限值
        /// </summary>
        /// <param name="theta"></param>
        /// <returns></returns>
        public override bool SetLimits(bool isPosLoading, double shearForce = 0)
        {
            //截面信息是否有误
            if (!this.isSectionCorrect()) return false;
            //设定承载力
            if (!this.SetCapacity(isPosLoading ? 0 : 180)) return false;
            //计算剪跨比
            var lamda = (float)this.Lammda;
            //计算轴压比
            var alr = this.AxialLoadRatio;
            //轴压比更新
            alr = alr < 0 ? 0 : alr;
            //如果是型钢
            if (this.isSRCSection())
            {
                //剪力为0
                if (shearForce == 0) return MessageBoxExtern.Error("型钢剪力墙需提供构件剪力！");
                //获得性能状态
                var level = new SRCWallLevel((float)this.msr, (float)lamda, (float)alr,
                    (float)this.LamdaV, this.GetVPR(shearForce), (float)this.SteelRatio);
                //获得限值和破坏状态
                this.limits = level.GetPerformList().ConvertAll(d => (double)d);
                this.damageMode = (DamageMode)level.GetFailureMode();
            }
            //混凝土
            else
            {
                //获得性能状态
                var level = new RCWallLevel((float)lamda, (float)this.msr, (float)alr, 
                    (float)this.bStirrupVRatio);
                //获得限值和破坏状态
                this.limits = level.GetRCPerformList().ConvertAll(d => (double)d);
                this.damageMode = (DamageMode)level.GetRCFailureMode();
            }
            return true;
        }

        /// <summary>
        /// 剪压比
        /// </summary>
        private float GetVPR(double shearForce)
        {
            //钢材强度
            var fa = ShearCapacityHelper.GetSteelStrength(this.wallSection.Steel_Grade,
                ShearCapacityHelper.CapacityType.Basic);
            //剪力
            var Vcw = shearForce - 0.32F * fa * this.Asteel / this.Lammda;
            //混凝土强度
            var fc = ShearCapacityHelper.GetConcreteStrength(this.wallSection.Concrete_Grade,
                false, ShearCapacityHelper.CapacityType.Basic);
            //返回剪压比
            return (float)Vcw / (fc * this.wallSection.Thickness * this.wallSection.Length);
        }

        /// <summary>
        /// 设定剪力墙截面
        /// </summary>
        /// <param name="length"></param>
        /// <param name="thicknees"></param>
        /// <param name="boundaryLengthI"></param>
        /// <param name="boundaryLengthJ"></param>
        /// <param name="boundaryAreaFactorI"></param>
        /// <param name="boundaryAreaFactorJ"></param>
        public void SetWallSection(double length, double thickness, double boundaryLength)
        {
            this.SetWallSection(length, thickness, boundaryLength, boundaryLength, 1, 1);
        }

        /// <summary>
        /// 一字墙截面
        /// </summary>
        /// <param name="length"> 墙长 </param>
        /// <param name="thickness"> 墙厚 </param>
        /// <param name="boundaryLengthI"> I端边缘构件长度 </param>
        /// <param name="boundaryLengthJ"> J端边缘构件长度 </param>
        public void SetWallSection(double length, double thickness, double boundaryLengthI, double boundaryLengthJ)
        {
            this.SetWallSection(length, thickness, boundaryLengthI, boundaryLengthJ, 1, 1);
        }

        /// <summary>
        /// 异形墙截面（L、T等）
        /// </summary>
        /// <param name="length"> 墙长 </param>
        /// <param name="thickness"> 墙厚 </param>
        /// <param name="boundaryLengthI"> I端边缘构件长度 </param>
        /// <param name="boundaryLengthJ"> J端边缘构件长度 </param>
        /// <param name="boundaryAreaFactorI"> I端边缘构件面积放大系数 </param>
        /// <param name="boundaryAreaFactorJ"> J端边缘构件面积放大系数 </param>
        public void SetWallSection(double length, double thickness, 
            double boundaryLengthI, double boundaryLengthJ, 
            double boundaryAreaFactorI, double boundaryAreaFactorJ)
        {
            this.wallSection.Length = (float)length;
            this.wallSection.Thickness = (float)thickness;
            this.boundaryI.bLength = boundaryLengthI;
            this.boundaryJ.bLength = boundaryLengthJ;
            this.boundaryI.tFactor = boundaryAreaFactorI;
            this.boundaryJ.tFactor = boundaryAreaFactorJ;
        }

        /// <summary>
        /// 设定剪力墙配筋信息
        /// </summary>
        /// <param name="vAsRatio"> 竖向分布筋配筋率 </param>
        /// <param name="hAsRatio"> 水平分布筋配筋率 </param>
        /// <param name="bAsRatioI"> I端边缘构件纵筋配筋率 </param>
        /// <param name="bAsRatioJ"> J端边缘构件纵筋配筋率 </param>
        /// <param name="bStirrupVRatio"> 边缘构件体积配箍率 </param>
        public void SetWallReinforcement(double vAsRatio, double hAsRatio, 
            double bAsRatioI, double bAsRatioJ, double bStirrupVRatio)
        {
            this.wallSection.Stirrup_S_Ratio = (float)hAsRatio;
            this.vRatio = vAsRatio;
            this.boundaryI.bAsRatio = bAsRatioI;
            this.boundaryJ.bAsRatio = bAsRatioJ;
            //体积配箍率
            this.bStirrupVRatio = bStirrupVRatio;
            this.boundaryI.bStirrupVRatio = bStirrupVRatio;
            this.boundaryJ.bStirrupVRatio = bStirrupVRatio;
        }

        /// <summary>
        /// 设定型钢及钢板
        /// </summary>
        /// <param name="steelRatioI"> I端边缘构件含钢率 </param>
        /// <param name="steelRatioJ"> J端边缘构件含钢率 </param>
        /// <param name="steelPlateThickness"> 钢板厚度 </param>
        public void SetWallSteel(double steelRatioI, double steelRatioJ, double steelPlateThickness = 0)
        {
            this.boundaryI.steelRatio = steelRatioI;
            this.boundaryJ.steelRatio = steelRatioJ;
            this.wallSection.Steel_Thickness = (float)steelPlateThickness;
        }
        
        /// <summary>
        /// 构造函数
        /// </summary>
        public WallSection(): base()
        {
            this.secion = new WALL_Section();
            this.wallSection.is_Elastic = false;
            this.boundaryI = new WallBoundarySection();
            this.boundaryJ = new WallBoundarySection();
        }

        /// <summary>
        /// 构造截面
        /// </summary>
        /// <param name="shearSpan"> 剪跨长度 mm </param>
        /// <param name="axialLoad"> 轴力 N </param>
        public WallSection(double shearSpan, double axialLoad) : this()
        {
            this.shearSpan = shearSpan;
            this.axialLoad = axialLoad;
        }
    }
}
